import requests
import json
import time
import logging

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# 禁用 SSL 证书验证（仅用于测试环境）
requests.packages.urllib3.disable_warnings()

def read_config():
    """读取配置文件并提取预期的BIOS设置"""
    try:
        with open('config.json', 'r') as f:
            # 过滤注释行
            content = ''.join(line for line in f if not line.strip().startswith(('//', '#')))
            config = json.loads(content)
            
            # 验证配置格式
            for i, device in enumerate(config):
                if 'bios_settings' not in device:
                    logger.error(f"设备 {i+1} 缺少 'bios_settings' 字段")
                    continue
                
                # 从 Attributes 中提取实际设置
                attributes = device['bios_settings'].get('Attributes', {})
                if not attributes:
                    logger.warning(f"设备 {i+1} 的 'bios_settings.Attributes' 为空")
                
                device['expected_settings'] = attributes  # 提取预期设置
            
            return config
    except FileNotFoundError:
        logger.error("配置文件 config.json 未找到，请检查。")
        return None
    except json.JSONDecodeError as e:
        logger.error(f"配置文件格式错误: {e}")
        return None

def get_system_id(redfish_url, username, password):
    """动态获取系统ID，替代硬编码的/Systems/1"""
    try:
        response = requests.get(f"{redfish_url}/Systems", auth=(username, password), verify=False)
        response.raise_for_status()
        systems = response.json()
        if 'Members' in systems and len(systems['Members']) > 0:
            system_path = systems['Members'][0]['@odata.id']
            system_id = system_path.split('/')[-1]
            logger.info(f"获取系统ID: {system_id}")
            return system_id
        else:
            logger.error(f"未找到系统资源，URL: {redfish_url}/Systems")
            return None
    except requests.RequestException as e:
        logger.error(f"获取系统ID失败: {e}")
        return None

def get_bios_settings_url(redfish_url, username, password):
    """获取BIOS设置的URL"""
    try:
        system_id = get_system_id(redfish_url, username, password)
        if not system_id:
            return None

        response = requests.get(f"{redfish_url}/Systems/{system_id}", auth=(username, password), verify=False)
        response.raise_for_status()
        system_data = response.json()
        bios_url = system_data.get("Bios", {}).get("@odata.id")

        if not bios_url:
            logger.error(f"未找到BIOS设置URL，设备地址: {redfish_url}")
            return None

        # 规范化URL
        if bios_url.startswith("/redfish/v1"):
            bios_url = bios_url[len("/redfish/v1"):]

        # 添加 /settings
        bios_url = f"{bios_url}/settings"
        return bios_url
    except requests.RequestException as e:
        logger.error(f"获取BIOS设置URL失败: {e}，设备地址: {redfish_url}")
        return None

def check_bios_settings(redfish_url, username, password, expected_settings, max_attempts=5, interval=30):
    """检查BIOS设置是否与预期值匹配"""
    logger.info(f"开始验证BIOS设置，预期设置: {expected_settings}")

    bios_url = get_bios_settings_url(redfish_url, username, password)
    if not bios_url:
        logger.error("无法获取BIOS设置URL，验证失败")
        return False

    for attempt in range(max_attempts):
        try:
            response = requests.get(f"{redfish_url}{bios_url}", auth=(username, password), verify=False)
            response.raise_for_status()
            current_settings = response.json().get("Attributes", {})

            # 检查所有预期设置是否匹配
            all_matched = True
            mismatched = []

            for key, expected_value in expected_settings.items():
                if key not in current_settings:
                    logger.warning(f"属性 {key} 不存在于当前BIOS设置中")
                    mismatched.append(key)
                    all_matched = False
                else:
                    # 比较当前值与预期值（处理布尔值、数字和字符串）
                    current_value = current_settings[key]
                    
                    # 特殊处理布尔值（如果预期是字符串"Enabled"，而实际是布尔值True）
                    if isinstance(current_value, bool) and isinstance(expected_value, str):
                        if (expected_value.lower() == "enabled" and not current_value) or \
                           (expected_value.lower() == "disabled" and current_value):
                            logger.warning(f"属性 {key} 值不匹配 - 预期: {expected_value}，实际: {current_value}")
                            mismatched.append(key)
                            all_matched = False
                    elif current_value != expected_value:
                        logger.warning(f"属性 {key} 值不匹配 - 预期: {expected_value}，实际: {current_value}")
                        mismatched.append(key)
                        all_matched = False

            if all_matched:
                logger.info("所有BIOS设置验证通过")
                return True
            else:
                logger.warning(f"尝试 {attempt + 1}/{max_attempts}: 部分设置未生效，未匹配的属性: {mismatched}")
                logger.info(f"当前BIOS设置: {json.dumps(current_settings, indent=2)}")

        except requests.RequestException as e:
            logger.error(f"尝试 {attempt + 1}/{max_attempts}: 获取BIOS设置失败 - {e}")

        if attempt < max_attempts - 1:
            logger.info(f"等待 {interval} 秒后再次检查...")
            time.sleep(interval)

    logger.error("验证超时，部分BIOS设置未生效")
    return False

def main():
    config = read_config()
    if config:
        for device in config:
            redfish_url = device['redfish_url']
            username = device['username']
            password = device['password']
            expected_settings = device.get('expected_settings', {})

            logger.info(f"检查设备: {redfish_url}")

            if not expected_settings:
                logger.warning("未指定需要验证的BIOS设置，跳过检查")
                continue

            # 检查BIOS设置是否生效
            settings_verified = check_bios_settings(redfish_url, username, password, expected_settings)

            if settings_verified:
                logger.info(f"设备 {redfish_url} 的BIOS设置验证成功")
            else:
                logger.error(f"设备 {redfish_url} 的BIOS设置验证失败")

if __name__ == "__main__":
    main()